/*!
 Temelia - Tree samples.

 Copyright (C) 2008 Ceata (http://ceata.org/proiecte/temelia).

 @author Dascalu Laurentiu

 This program is free software; you can redistribute it and
 modify it under the terms of the GNU General Public License
 as published by the Free Software Foundation; either version 3
 of the License, or (at your option) any later version.

 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.

 You should have received a copy of the GNU General Public License
 along with this program; if not, write to the Free Software
 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 */

#include "include/samples.h"
#include <temelia/tree.h>
#include <temelia/tree_algorithms.h>
#include <temelia/vector.h>
#include <temelia/linked_list.h>

static void sample1(int type)
{
	tree_t tree;

	PRINT("\n\n Sample 1 started \n\n");

	tree = tree_new(NULL, type);
	PRINT("Height %d\nSize %d\n", tree_get_height(tree), tree_get_size(tree));
	PRINT("Empty %d\nLeaf %d\n", tree_is_empty(tree), tree_is_leaf(tree));

	// work with address memories.
	PRINT("key %lu\n", (unsigned long) tree_get_key(tree));
	tree_set_key(tree, (void *) 0x010);
	PRINT("new key %lu\n", (unsigned long) tree_get_key(tree));

	PRINT("parent %p, children number %d\n", tree_get_parent(tree),
			tree_get_children_number(tree));

	tree_delete_node(tree);

	PRINT("\n\n Sample 1 ended \n\n");
}

static void sample2(int type)
{
	tree_t tree, root;
	int i, j, k, N = 5;

	PRINT("\n\n Sample 2 started \n\n");

	k = 0;
	tree = tree_new(int_new(k++), type);

	for (i = 0; i < N; i++)
	{
		for (j = 0; j < i + 2; j++)
			tree_add_child(tree, tree_new(int_new(k++), type));
		tree = tree_get_child(tree, 0);
	}

	root = tree_get_root(tree);

	PRINT("Children number : %d\n", tree_get_children_number(tree_get_parent(
							tree)));
	PRINT("Tree size : %d\n", tree_get_size(root));
	PRINT("Tree height : %d\n", tree_get_height(root));

	PRINT("\nPrinting the tree ...\n");
	tree_bfs_iterate(root, int_handler, NULL);

	PRINT("\nRemoving a sub-tree ...\n");

	while (tree_get_parent(tree) != root)
		tree = tree_get_parent(tree);

	tree_remove_from_parent(tree);
	PRINT("\nPrinting the root tree after removing one of it's children ...\n");
	tree_bfs_iterate(root, int_handler, NULL);
	tree_bfs_iterate(root, int_delete, NULL);

	PRINT("\nPrinting the removed tree ...\n");
	tree_bfs_iterate(tree, int_handler, NULL);
	tree_bfs_iterate(tree, int_delete, NULL);

	// Delete the two trees.
	tree_delete(root);
	tree_delete(tree);

	PRINT("\n\n Sample 2 ended \n\n");
}

static void sample3(int type)
{
	long int *x = (long int *) 0x123456, i, N = 100000;

	PRINT("\n\n Sample 3 started \n\n");

	for (i = 0; i < N; i++)
		tree_delete_node(tree_new(x, type));

	PRINT("\n\n Sample 3 ended \n\n");
}

static void sample4(int type)
{
	tree_t root, node;
	int i, N = 10;
	void *children, *it;

	root = tree_new(int_new(-1), type);

	for (i = 0; i < N; i++)
	{
		node = tree_new(int_new(i * i), type);
		tree_set_parent(root, node);
	}

	// BFS iterate
	tree_bfs_iterate(root, int_handler, NULL);
	PRINT("\nIterating over children nodes\n");

	// User defined iteration
	children = tree_get_children(root);

	if (type)
	{
		for (it = linked_list_get_begin(children); it; it
				= linked_list_iterator_get_next(it))
			int_handler(tree_get_key(linked_list_iterator_get_key(it)), NULL);
	}
	else
	{
		for (i = 0; i < vector_get_size(children); i++)
			int_handler(tree_get_key(vector_get_key_at(children, i)), NULL);
	}

	PRINT("\n");

	// Free the user-space allocated memory
	tree_bfs_iterate(root, int_delete, NULL);

	N = tree_get_children_number(root);
	for (i = 0; i < N; i++)
		tree_delete_node(tree_remove_child(root, 0));

	tree_delete_node(root);
}

void run_tree_samples()
{
	int i;

	// Activate logging
	//INIT(stdout);

	for (i = 0; i <= 1; i++)
	{
		if (i == 0)
			PRINT("\n === Vector backbone ===");
		else
			PRINT("\n === Linked list backbone ===");

		sample1(i);
		sample2(i);
		sample3(i);
		sample4(i);
	}

	//DESTROY();
}
